package repositories

import (
	"gitee.com/golanglearn/small/database"
	"gitee.com/golanglearn/small/models"
)

type SceneRepository interface {
	Create(p *models.Scene) error
	GetAll(tid int) ([]*models.Scene, error)
	GetAllOfUid(tid int) ([]*models.Scene, error)
	FindById(uid, tid int) (*models.Scene, error)
	Delete(uis, tid int) error
	Paginate(tid int, perpage int, offset int) ([]*models.Scene, error)
	GetTotalSceneCount(tid int) (int, error)
}

type sceneRepository struct {
	*database.MySQLDB
}

func NewSceneRepository(db *database.MySQLDB) SceneRepository {
	return &sceneRepository{db}
}

func (sr *sceneRepository) Create(s *models.Scene) error {

	stmt, err := sr.DB.Prepare("INSERT INTO scene SET t_id=?, u_id=?, created_at=?")
	if err != nil {
		return err
	}
	defer stmt.Close()
	result, err := stmt.Exec(s.TID, s.UID, s.CreatedAt.Format("20060102150405"))
	if err != nil {
		return err
	}

	sId, err := result.LastInsertId()
	if err != nil {
		return err
	}
	s.ID = int(sId)

	return nil
}

func (sr *sceneRepository) GetAll(tid int) ([]*models.Scene, error) {
	var scenes []*models.Scene

	rows, err := sr.DB.Query("SELECT s.id, u.name name, s.created_at, s.updated_at FROM scene s INNER JOIN users u ON s.u_id = u.id where s.t_id = ?", tid)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		s := new(models.Scene)
		err := rows.Scan(&s.ID, &s.Name, &s.CreatedAt, &s.UpdatedAt)
		if err != nil {
			return nil, err
		}
		scenes = append(scenes, s)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	return scenes, nil
}

func (sr *sceneRepository) GetAllOfUid(tid int) ([]*models.Scene, error) {
	var scenes []*models.Scene

	rows, err := sr.DB.Query("SELECT u_id FROM scene WHERE t_id = ?", tid)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		s := new(models.Scene)
		err := rows.Scan(&s.UID)
		if err != nil {
			return nil, err
		}
		scenes = append(scenes, s)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	return scenes, nil
}

func (sr *sceneRepository) GetTotalSceneCount(tid int) (int, error) {
	var count int
	err := sr.DB.QueryRow("SELECT COUNT(*) FROM scene WHERE t_id = ?", tid).Scan(&count)
	if err != nil {
		return -1, err
	}

	return count, nil
}

func (sr *sceneRepository) Paginate(tid int, perpage int, offset int) ([]*models.Scene, error) {
	var scenes []*models.Scene

	rows, err := sr.DB.Query("SELECT s.id, u.name name, s.created_at, s.updated_at FROM scene s INNER JOIN users u ON s.u_id = u.id WHERE s.t_id = ? LIMIT ? OFFSET ?", tid, perpage, offset)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	for rows.Next() {
		s := new(models.Scene)
		err := rows.Scan(&s.ID, &s.Name, &s.CreatedAt, &s.UpdatedAt)
		if err != nil {
			return nil, err
		}
		scenes = append(scenes, s)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	return scenes, nil
}

func (sr *sceneRepository) FindById(uid, tid int) (*models.Scene, error) {
	scene := models.Scene{}

	err := sr.DB.QueryRow("SELECT s.id, u.name name, s.u_id, s.created_at, s.updated_at FROM scene s INNER JOIN users u ON s.u_id = u.id WHERE s.u_id = ? AND s.t_id = ?", uid, tid).Scan(&scene.ID, &scene.Name, &scene.UID, &scene.CreatedAt, &scene.UpdatedAt)
	if err != nil {
		return nil, err
	}

	return &scene, nil
}

func (sr *sceneRepository) Delete(uid, tid int) error {
	stmt, err := sr.DB.Prepare("DELETE FROM scene WHERE t_id = ? AND u_id = ?")
	if err != nil {
		return err
	}
	defer stmt.Close()
	_, err = stmt.Exec(tid, uid)
	if err != nil {
		return err
	}

	return nil
}
